package edu.wpi.cs509.ui;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.*;

import javax.swing.BoxLayout;

import edu.wpi.cs509.representation.GameListItem;
import edu.wpi.cs509.ui.menu.MenuActionQuit;

/**
 * Game List Panelclass extends JPanel implements ListSelectionListener.
 * This is the main Panel displayed after the user has logged in.
 * This display will create and provide to the application screen the following:
 * 		List of active games, 
 *  	Button to Join a selected game,
 * 		Button to Observe a selected game,
 *  	Button to start a new Game,
 *  	Button to refresh the list of active games,
 *  	Button to quit
 * @author jefmarti
 *
 *
 */
@SuppressWarnings("serial")
public class GameListPanel extends JPanel {
	
	private JButton newGameButton;
	private JButton refreshGameListButton;
	private JButton quitButton;
	private JPanel joinGameListPanel;
	private JPanel coreGameListPanel;
	private JScrollPane gameListScrollPane;
	private A__MainStrategoClient client;
	
	private static final String joinString = "Join";
	private static final String observeString = "Observe";
	private static final String newGameString = "New Game";
	private static final String refreshListString = "Refresh";
	private static final String activeGamesString = "Active Games";
	private static final String quitString = "Quit";

	/**
	 * Method to print out a trace within the GLP
	 * @param func
	 */
	private void trace(String func) {
		System.out.println("UI GLP: ----- "+func+" -----> ClientLogic");
	}
	
	/**
	 * GameListPanel Constructor. This creates the Panels that are displayed as the games list
	 * @param client - This is the Stratego client object. This is used when creating the buttons
	 * 
	 */
	public GameListPanel( A__MainStrategoClient client ) {
		
		super(new BorderLayout());
		
		this.client = client;
		
		/**
		 * Forced to use a BoxLayout because the other option like to limit the coding ability
		 * of creating a dynamic set of panels and not overwrite the details on in the frame.
		 * Set the layout.
		 */
		
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

		/**
		 * Create the active Game String in a sub panel.
		 * This is done by creating a jPanel and adding a JLabel to this panel
		 */
		JPanel activeGamesStringPanel = new JPanel();
		JLabel gameListPanelLabel = new JLabel(activeGamesString);
		activeGamesStringPanel.add(gameListPanelLabel);
		activeGamesStringPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
		
		/**
		 * Create the New Game, refresh List and Quit buttons and add it to 
		 * a subpanel for display. This is done to separate the panels so they will not overwrite
		 * each other.
		 */
		newGameButton = new JButton(newGameString);
		newGameButton.addActionListener(new buttonActionNewGame(client));
		refreshGameListButton = new JButton(refreshListString);
		refreshGameListButton.addActionListener(new buttonActionRefreshList(client));
		
		quitButton = new JButton(quitString);
		quitButton.addActionListener(new MenuActionQuit(client));
		JPanel buttonPane = new JPanel();
		buttonPane.add(newGameButton);
		buttonPane.add(refreshGameListButton);
		buttonPane.add(quitButton);
		buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));	


		/**
		 * Place the Active Games List Text Panel on the display
		 */
		add(activeGamesStringPanel);	
		
		/**
		 * Create the Actual Game list panel and place on the panel frame.
		 */
		coreGameListPanel = new JPanel();
		gameListScrollPane = new JScrollPane(coreGameListPanel);
		joinGameListPanel = new JPanel();
		coreGameListPanel.add(joinGameListPanel);
		
		add( gameListScrollPane );
		
		/**
		 * Place the New, Refresh and Quit buttons panel on the panel frame.
		 */

		add(buttonPane);
	}
	
	/**
	 * Action New Game button class to invoke a new game.
	 * This class creates a button and creates an action listener for
	 * that button to start a new game when selected.
	 * @author jefmarti
	 *
	 */
	public class buttonActionNewGame implements ActionListener {
		
		private A__MainStrategoClient client;
		
		/**
		 * Constructor for the action listener
		 * @param client
		 */
		public buttonActionNewGame(A__MainStrategoClient client) {
			this.client = client;
		}
		
		/**
		 * actionPerformed Handler for the new game button action event
		 */
		@Override
		public void actionPerformed(ActionEvent e) {	
			client.startNewGame();
			trace("actionPerformed() startNewGame()");
		}
	}
	
	/**
	 * Action refresh button class to get the current active list of games from the server. The
	 * Action performed method requests the list of active games from the Server, adds to the list and
	 * displays the list. Also provides a dialog if there are not games on the server.
	 * @author jefmarti
	 */
	public class buttonActionRefreshList implements ActionListener {
		private A__MainStrategoClient client;
		
		/**
		 * Constructor for the action listener
		 * @param client
		 */
		public buttonActionRefreshList(A__MainStrategoClient client) {
		    this.client = client;
		}
		
		/**
		 * actionPerformed Handler for refresh list action event The
		 * Action performed method requests the list of active games from the Server, adds to the list and
		 * displays the list. Also provides a dialog if there are not games on the server.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			trace("actionPerformed() gateGame()");
			client.getGames();
		}
		
	}
  
    /**
     * Action Join game button class to join an active game
     * @author jefmarti
     *
     */
	public class buttonActionJoin implements ActionListener {
		private A__MainStrategoClient client;
		private GameListItem game;
		
		/**
		 * Constructor for the action listener
		 * @param client game
		 */
		public buttonActionJoin(A__MainStrategoClient client, GameListItem game) {
			this.client = client;
			this.game = game;
		}
		
		/**
		 * actionPerformed Handler for action event to actually join the game.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			trace("actionPerformed() joinGame()");
			client.joinGame(game.getGameID());
		}
	}

    /**
     * Action Join game button class to join an active game
     * @author jefmarti
     *
     */
	public class buttonActionObserve implements ActionListener {
		private A__MainStrategoClient client;
		private GameListItem game;

		/**
		 * Constructor for the action listener
		 * @param client 
		 */
		public buttonActionObserve(A__MainStrategoClient client, GameListItem game) {
			this.client = client;
			this.game = game;
		}
		
		/**
		 * actionPerformed Handler for action event, currently just create a dummy gameboard
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			trace("actionPerformed() addObserveGame()");
			client.addObserveGame(game.getGameID());
		}
	}
	
	/** 
	 * setJoinGameList, is a primitive method that will construct panels
	 * and add them to a gameList panel, add that panel back to the main panel
	 * and repaint the screen. Why is this primitive, because the core language
	 * does not seem to have advance GUI interfaces to do the right thing. If this point of
	 * view is in question, then just read the GridLayout method and explain why it
	 * will decide for me the parameters that I tell it will be ignored ;)
	 * @param gamesList
	 */
	private void setGameList( List<GameListItem> gamesList ) {
		
		System.out.println("UI GLP: setGameList called");
		
		// The great Java Language apparently cannot handle
		// Setting the objects in the Gridlayout with the parameters passed in
		// It will just ignore them when it deems fit. Also the display of objects
		// Is also troublesome at best because it likes not to display them. JEM
		/**
		 * Contruct a monolithic gridbag structure and increment through the positions
		 * to place the objects on the screen.
		 */
		if (gamesList != null ) {
			joinGameListPanel.removeAll();
			joinGameListPanel.setLayout(new GridBagLayout());
			joinGameListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
            GridBagConstraints constraints = new GridBagConstraints();
            constraints.gridx = 0;
            constraints.gridy = 1;
            constraints.gridwidth = 1;
            constraints.gridheight = 2;
            constraints.weightx = 100.0;
            constraints.weighty = 100.0;
            constraints.fill = GridBagConstraints.NONE;
            constraints.anchor = GridBagConstraints.CENTER;
            constraints.insets = new Insets(2,2,2,2);
            joinGameListPanel.setVisible(false);
            
            JLabel n1nextTextField = new JLabel("Player 1");
			joinGameListPanel.add(n1nextTextField, constraints);
			JLabel nnextJoinButton = new JLabel("Player 2");
			constraints.gridx++;
			joinGameListPanel.add(nnextJoinButton, constraints);
			constraints.gridx++;
			JLabel nnextObserveButton = new JLabel("Observe", 10);
			joinGameListPanel.add(nnextObserveButton, constraints);
			constraints.gridx = 0;
			constraints.gridy+=2;
            
		    Iterator<GameListItem> itr = gamesList.iterator();
		    while(itr.hasNext()) {
		    	GameListItem element = itr.next();
				JLabel nextPlayer1 = new JLabel(element.getPlayer1Name());
				joinGameListPanel.add(nextPlayer1, constraints);
				constraints.gridx++;
				
				if (element.isJoinable()) {
				    JButton nextJoinButton = new JButton(joinString);
				    nextJoinButton.addActionListener(new buttonActionJoin(client, element));
				    joinGameListPanel.add(nextJoinButton, constraints);
					constraints.gridx++;
				} else {
					JLabel nextPlayer2 = new JLabel(element.getPlayer2Name(), 10);
					joinGameListPanel.add(nextPlayer2, constraints);
					constraints.gridx++;
				}
				JButton nextObserveButton = new JButton(observeString);
				nextObserveButton.addActionListener(new buttonActionObserve(client, element));
				joinGameListPanel.add(nextObserveButton, constraints);
				constraints.gridx = 0;
				// Why the += 2? Because if you use 1 it will over lap the next on the first
				// And you cannot see it, Great !
				constraints.gridy+=2;
				validate();
		    }
		    
		    joinGameListPanel.setVisible(true);
		    
		} else {			
			Dialog.displayNoGamesOnServer();
		}
		
		validate();
		repaint();
	}

	/**
	 * Wrapper to call the setGamesList method to update the panel with
	 * the list of games provided from the server and client logic.
	 * @param games
	 */
	public void setGames(List<GameListItem> games) {
		System.out.println("UI GLP: setGames called");
		setGameList( games );
	}

}